package com.im.users.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.druid.sql.visitor.functions.If;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.im.common.redis.RedisKeys;
import com.im.common.utils.*;
import com.im.common.vo.MatchVo;
import com.im.feign.service.DynamicService;
import com.im.security.dto.LoginVo;
import com.im.users.entity.FansEntity;
import com.im.users.entity.FollowerEntity;
import com.im.users.service.FansService;
import com.im.users.service.FollowerService;
import com.im.users.utils.JWTUtils;
import com.im.users.entity.UserEntity;
import com.im.users.mapper.UserDao;
import com.im.users.service.UserService;
import com.im.users.vo.DetialVo;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service("userService")
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {

    @Autowired
    private FansService fansService;

    @Autowired
    private DynamicService dynamicService;

    @Autowired
    private FollowerService followerService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<UserEntity> page = this.page(new Query<UserEntity>().getPage(params), new QueryWrapper<UserEntity>());
        return new PageUtils(page);
    }

//    public com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
//        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
//                // 必填，您的 AccessKey ID
//                .setAccessKeyId("LTAI5t5asVAxyCbEZNccFjrG")
//                // 必填，您的 AccessKey Secret
//                .setAccessKeySecret("qGyfMxTregFSat5dIAjFmUMhcKTPaj");
//        // 访问的域名
//        config.endpoint = "dysmsapi.aliyuncs.com";
//        return new com.aliyun.dysmsapi20170525.Client(config);
//    }
//
//    /**
//     * 使用STS鉴权方式初始化账号Client，推荐此方式。
//     * @param accessKeyId
//     * @param accessKeySecret
//     * @param securityToken
//     * @return Client
//     * @throws Exception
//     */
//    public static com.aliyun.dysmsapi20170525.Client createClientWithSTS(String accessKeyId, String accessKeySecret, String securityToken) throws Exception {
//        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
//                // 必填，您的 AccessKey ID
//                .setAccessKeyId(accessKeyId)
//                // 必填，您的 AccessKey Secret
//                .setAccessKeySecret(accessKeySecret)
//                // 必填，您的 Security Token
//                .setSecurityToken(securityToken)
//                // 必填，表明使用 STS 方式
//                .setType("sts");
//        // 访问的域名
//        config.endpoint = "dysmsapi.aliyuncs.com";
//        return new com.aliyun.dysmsapi20170525.Client(config);
//    }

    @Override
    public R login(Map map) throws Exception {

        String tel = (String) map.get("tel");
        String code = (String) map.get("code");
        String cid = (String) map.get("cid");
        //TODO 验证验证码是否正确
        log.debug("tel:{}");
        log.debug("code:{}");
        log.debug("cid:{}");
        LambdaQueryWrapper<UserEntity> eq = new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getPhone, tel);
        UserEntity one = this.getOne(eq);
        log.debug("one:{}", one);
//        创建新的Vo对象返回数据
        LoginVo loginVo = new LoginVo();
        BeanUtils.copyProperties(one, loginVo);
//        获取用户粉丝数量
        Long fansCount = fansService.getFansCount(one.getIdNum());
//          获取关注数量
        Long followerCount = followerService.getFollowerCount(one.getIdNum());
//          获取用户动态数量
        //        查询用户发表的动态数量
//        List list = dynamicService.list(uid);
//        int size = list.size();
        Integer size = 99;
//        if (list == null) {
//            size = 999;
//        }
        loginVo.setArticleNum(size);
        loginVo.setIdolsNum(followerCount);
        loginVo.setFansNum(fansCount);
        loginVo.setCreateTime((Timestamp) one.getCreateTime());
        log.debug("loginVo:{}", loginVo);
//        BeanUtils.copyProperties(one,loginVo.getUserInfo());
        String loginUserJson = JSONObject.toJSONString(loginVo);
        String jwt = JWTUtils.createToken(loginUserJson);
        loginVo.setToken(jwt);
        return R.seccess(loginVo);
    }

    /**
     * 根据用户ID更新用户最近登陆时间
     *
     * @param map
     * @return
     */

    @Override
    public R updateLoginTime(Map map) {
        Integer userId = Integer.parseInt(map.get("userId").toString());
        long id = Long.parseLong(userId.toString());
        UserEntity userEntity = new UserEntity();
        userEntity.setId(id);
        userEntity.setLastLoginTime(new Date());
        boolean result = updateById(userEntity);
        return R.out(result);
    }

//    private Long getFollowerCount(Integer idNum) {
//        LambdaQueryWrapper<FollowerEntity> queryWrapper = new LambdaQueryWrapper<FollowerEntity>().eq(FollowerEntity::getUserNum, idNum);
//        long followerCount = followerService.count(queryWrapper);
//        return followerCount;
//    }
//
//
//    public Long getFansCount(Integer idNum) {
//        LambdaQueryWrapper<FansEntity> queryWrapper = new LambdaQueryWrapper<FansEntity>().eq(FansEntity::getUserNum, idNum);
//        long fansCount = fansService.count(queryWrapper);
//        return fansCount;
//    }


    /**
     * 获取用户详情
     *
     * @param uid
     * @return
     */
    @Override
    public DetialVo getUserDetail(Integer uid) {
//        获取用户基本信息
        UserEntity user = baseMapper.selectById(uid);
//        查询用户的粉丝数量
        Long fansCount = fansService.getFansCount(user.getIdNum());
//        查询用户关注数量
        Long followerCount = followerService.getFollowerCount(user.getIdNum());
//        TODO
//        查询用户发表的动态数量
//        List list = dynamicService.list(uid);
//        int size = list.size();
        Integer size = 99;
//        if (list == null) {
//            size = 999;
//        }
//        封装成vo对象
        DetialVo detialVo = new DetialVo();
        detialVo.setFansNum(fansCount);
        detialVo.setIdolsNum(followerCount);
        detialVo.setArticleNum(size);
        BeanUtils.copyProperties(user, detialVo);
        System.out.println("拷贝结果:" + detialVo);
        return detialVo;
    }

    @Override
    public List getMatch(MatchVo matchVo, LoginVo loginVo) {
        System.out.println("matchVo:+" + matchVo);
        //        初始距离100km
        Double around = 100D;
//        每页显示条数
        Integer pageSize = 5;
        String userLocationKey = RedisKeys.getUserLocationKey();
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getSex, matchVo.getSex()).ge(UserEntity::getAge, matchVo.getMinAge()).le(UserEntity::getAge, matchVo.getMaxAge());
//        匹配同城用户
        ArrayList<Integer> list = new ArrayList<>();
        if (matchVo.getDistanceActive().equals(1)) {
//            获取redis key
//            构造查询条件
            Distance distance = new Distance(around, RedisGeoCommands.DistanceUnit.KILOMETERS);
//            查询redis
            GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = stringRedisTemplate.opsForGeo()
                    .radius(userLocationKey, "123", distance);
            List<GeoResult<RedisGeoCommands.GeoLocation<String>>> content = geoResults.getContent();
//            遍历结果获取用户ID
            for (GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult : content) {
                RedisGeoCommands.@NonNull GeoLocation<String> geoResultContent = geoResult.getContent();
//                添加到list中，用于mybatisplus in的查询条件。
                list.add(Integer.parseInt(geoResultContent.getName()));
            }
            wrapper.in(UserEntity::getId, list);
        }
        Page<UserEntity> page = new Page<>(matchVo.getPageIndex(), pageSize);
        page = this.page(page, wrapper);
        List<UserEntity> records = page.getRecords();
//        如果100公里内，没有用户存在，或者存在的用户不足5，则扩大搜索距离
        if (CollectionUtil.isEmpty(records) || records.size() <= pageSize) {
            around += 100;
            Distance distance = new Distance(around, RedisGeoCommands.DistanceUnit.KILOMETERS);
//            查询redis
            GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = stringRedisTemplate.opsForGeo().radius(userLocationKey, "21", distance);
            List<GeoResult<RedisGeoCommands.GeoLocation<String>>> content = geoResults.getContent();
//            遍历结果获取用户ID
            for (GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult : content) {
                RedisGeoCommands.@NonNull GeoLocation<String> geoResultContent = geoResult.getContent();
//                添加到list中，用于mybatisplus in的查询条件。
                list.add(Integer.parseInt(geoResultContent.getName()));
            }
            wrapper.in(UserEntity::getId, list);
            Page<UserEntity> newPage = new Page<>(matchVo.getPageIndex(), pageSize);
            page = this.page(page, wrapper);
            records = page.getRecords();
        }
        return records;
    }
}